package setting

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"likeadmin/admin/schemas/req"
	"likeadmin/admin/schemas/resp"
	"likeadmin/core/response"
	"likeadmin/dao"
	"likeadmin/util"
	"sort"
)

type IPaySettingService interface {
	List(c *gin.Context) (res []resp.PaySettingResp, e error)
	Detail(c *gin.Context, name string) (res resp.PaySettingResp, e error)
	Set(c *gin.Context, editReq req.PaySettingEditReq) (e error)
	GetWay(c *gin.Context) (all map[string][]resp.PaySceneResp, e error)
	SetWay(c *gin.Context, setReq map[string][]req.PaySceneSetReq) (e error)
}

// NewPaySettingService 初始化
func NewPaySettingService(db *gorm.DB, dao *dao.Query) IPaySettingService {
	return &paySettingService{db: db, dao: dao}
}

// paySettingService 通知设置服务实现类
type paySettingService struct {
	db  *gorm.DB
	dao *dao.Query
}

// List 通知设置列表
func (srv paySettingService) List(c *gin.Context) (res []resp.PaySettingResp, e error) {

	data, err := util.ConfigUtil.Get(srv.db, "pay_config")
	if e = response.CheckErr(err, "Detail Get err"); e != nil {
		return
	}

	for _, name := range data {
		if name != "" {
			var item resp.PaySettingResp
			err := json.Unmarshal([]byte(name), &item)
			// 排除 default 值
			if err != nil {
				continue
			}
			item.Icon = util.UrlUtil.ToAbsoluteUrl(item.Icon)
			res = append(res, item)
		}
	}

	// 按照排序字段进行排序
	sort.Slice(res, func(i, j int) bool {
		return res[i].Sort < res[j].Sort
	})

	return res, nil
}

// Detail 支付设置详情
func (srv paySettingService) Detail(c *gin.Context, name string) (res resp.PaySettingResp, e error) {
	data, err := util.ConfigUtil.GetVal(srv.db, "pay_config", name, "")
	if e = response.CheckErr(err, "Detail Get err"); e != nil {
		return
	}
	var item resp.PaySettingResp
	_ = json.Unmarshal([]byte(data), &item)
	response.Copy(&res, item)
	res.Icon = util.UrlUtil.ToAbsoluteUrl(res.Icon)
	return
}

// Set 设置支付配置
func (srv paySettingService) Set(c *gin.Context, editReq req.PaySettingEditReq) (e error) {
	editReq.Icon = util.UrlUtil.ToRelativeUrl(editReq.Icon)
	marshal, err := json.Marshal(editReq)
	if err != nil {
		if e = response.CheckErr(err, "Save Set name err"); e != nil {
			return
		}
	}

	err = util.ConfigUtil.Set(srv.db, "pay_config", editReq.Name, string(marshal))
	if e = response.CheckErr(err, "Save Set name err"); e != nil {
		return
	}

	return
}

// GetWay 获取支付方式
func (srv paySettingService) GetWay(c *gin.Context) (all map[string][]resp.PaySceneResp, e error) {
	// 获取支付方式列表
	config, err := util.ConfigUtil.Get(srv.db, "pay_config")
	if e = response.CheckErr(err, "Detail Get err"); e != nil {
		return
	}

	Cfg := make(map[string]resp.PaySettingResp)
	for payName := range config {
		if config[payName] != "" {
			var item resp.PaySettingResp
			err = json.Unmarshal([]byte(config[payName]), &item)
			// 排除 default 值
			if err != nil {
				continue
			}
			item.Icon = util.UrlUtil.ToAbsoluteUrl(item.Icon)
			Cfg[payName] = item
		}
	}

	data, err := util.ConfigUtil.Get(srv.db, "pay_scene")
	if e = response.CheckErr(err, "Detail Get err"); e != nil {
		return
	}

	var respall = make(map[string][]resp.PaySceneResp)

	for sceneName := range data {
		var res []resp.PaySceneResp

		if data[sceneName] != "" {
			var items []resp.PaySceneResp
			err = json.Unmarshal([]byte(data[sceneName]), &items)
			// 排除 default 值
			if err != nil {
				continue
			}
			res = append(res, items...)
			// 更新支付的配置项
			for i, _ := range res {
				res[i].PaymentName = Cfg[res[i].PaymentName].Name
				res[i].DisplayName = Cfg[res[i].PaymentName].DisplayName
				res[i].Icon = Cfg[res[i].PaymentName].Icon
			}

		} else {
			// 没有配置项时给定默认项
			for payment := range Cfg {
				res = append(res, resp.PaySceneResp{
					Scene:       sceneName,
					IsDefault:   0,
					Status:      0,
					PaymentName: payment,
					DisplayName: Cfg[payment].DisplayName,
					Icon:        Cfg[payment].Icon,
				})
			}
		}
		respall[sceneName] = res
	}

	return respall, nil
}

// SetWay 设置支付方式
func (srv paySettingService) SetWay(c *gin.Context, setReq map[string][]req.PaySceneSetReq) (e error) {

	for name := range setReq {
		marshal, err := json.Marshal(setReq[name])
		if err != nil {
			if e = response.CheckErr(err, "Save Set name err"); e != nil {
				break
			}
		}
		err = util.ConfigUtil.Set(srv.db, "pay_scene", name, string(marshal))
		if e = response.CheckErr(err, "Save Set name err"); e != nil {
			break
		}
	}

	return
}
